using System;
using System.Collections.Generic;
using System.Text;
using DslModeling = global::Microsoft.VisualStudio.Modeling;
using DslDesign = global::Microsoft.VisualStudio.Modeling.Design;
using Microsoft.VisualStudio.Modeling.Design;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling.Validation;

namespace Evaluant.EussDSL
{
    /// <summary>
    /// Redefinition of the Identifier Constructor
    /// </summary>
    [TypeDescriptionProvider(typeof(IdentifierPropertyProvider))]
    [ValidationState(ValidationState.Enabled)]
    public partial class Identifier : DslModeling::ModelElement
    {
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="store">Store where new element is to be created.</param>
        /// <param name="propertyAssignments">List of domain property id/value pairs to set once the element is created.</param>
        public Identifier(DslModeling::Store store, params DslModeling::PropertyAssignment[] propertyAssignments)
            : this(store != null ? store.DefaultPartition : null, propertyAssignments)
        {
            string entityType = (Entity == null) ? "" : Entity.type;
            field = entityType + "Id";
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="partition">Partition where new element is to be created.</param>
        /// <param name="propertyAssignments">List of domain property id/value pairs to set once the element is created.</param>
        public Identifier(DslModeling::Partition partition, params DslModeling::PropertyAssignment[] propertyAssignments)
            : base(partition, propertyAssignments)
        {
            string entityType = (Entity == null) ? "" : Entity.type;
            field = entityType + "Id";
        }


        internal sealed partial class GeneratorNamePropertyHandler
        {
            protected override void OnValueChanged(Identifier element, string oldValue, string newValue)
            {
                if (string.IsNullOrEmpty(newValue))
                {
                    throw new ArgumentOutOfRangeException("GeneratorName", "The Name of the Generator cannot be empty or null.");
                }
                if (!GlobalData.generatorNames.Contains(newValue))
                {
                    string message = "The Name of the Generator should match one the values";
                    foreach (string genName in GlobalData.generatorNames)
                    {
                        message += " '" + genName + "',";
                    }
                    message = message.Substring(0, message.Length - 1) + ".";
                    throw new ArgumentOutOfRangeException("GeneratorName", message);
                }
                base.OnValueChanged(element, oldValue, newValue);
                if (element.Entity != null)
                {
                    InheritanceDetector.DetectAndShow(element.Entity);
                }
            }
        }

        internal sealed partial class fieldPropertyHandler
        {
            protected override void OnValueChanged(Identifier element, string oldValue, string newValue)
            {
                if (string.IsNullOrEmpty(newValue))
                {
                    throw new ArgumentOutOfRangeException("Field", "Field cannot be empty or null.");
                }
                base.OnValueChanged(element, oldValue, newValue);
                if (element.Entity != null)
                {
                    InheritanceDetector.DetectAndShow(element.Entity);
                }
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void ValidGeneratorName(ValidationContext context)
        {
            if (!GlobalData.generatorNames.Contains(GeneratorName))
            {
                context.LogError("The 'GeneratorName' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is invalid. Check the documentation or use the dropdown to obtain the list of valid generator names.", "005", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void ValidDbType(ValidationContext context)
        {
            if (!string.IsNullOrEmpty(dbType) && !GlobalData.dbTypes.Contains(dbType))
            {
                context.LogError("The 'dbType' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is invalid. Check the documentation or use the dropdown to obtain the list of valid EUSS database types.", "006", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void ValidSeed(ValidationContext context)
        {
            int res;
            if (!string.IsNullOrEmpty(seed) && !int.TryParse(seed, out res))
            {
                context.LogError("The 'seed' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is not an Integer.", "007", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void ValidIncrement(ValidationContext context)
        {
            int res;
            if (!string.IsNullOrEmpty(increment) && !int.TryParse(increment, out res))
            {
                context.LogError("The 'increment' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is not an Integer.", "008", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void ValidSize(ValidationContext context)
        {
            int res;
            bool success = int.TryParse(size, out res);
            if (!string.IsNullOrEmpty(size) && !success)
            {
                context.LogError("The 'size' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is not an Integer.", "009", this.Entity);
            }
            if (success && res <= 0)
            {
                context.LogError("The 'size' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' is not a positive Integer.", "009", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void DbTypeExistence(ValidationContext context)
        {
            if (!string.IsNullOrEmpty(dbType) && (GeneratorName != "assigned" && GeneratorName != "native"))
            {
                context.LogWarning("The 'dbtype' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' will be ignored because the generator name is not 'assigned' or 'native'.", "010", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void SeedExistence(ValidationContext context)
        {
            if (!string.IsNullOrEmpty(seed) && GeneratorName != "native")
            {
                context.LogWarning("The 'seed' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' will be ignored because the generator name is not 'native'.", "011", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void IncrementExistence(ValidationContext context)
        {
            if (!string.IsNullOrEmpty(increment) && GeneratorName != "native")
            {
                context.LogWarning("The 'increment' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' will be ignored because the generator name is not 'native'.", "012", this.Entity);
            }
        }

        [ValidationMethod(ValidationCategories.Menu | ValidationCategories.Save)]
        private void SizeExistence(ValidationContext context)
        {
            if (!string.IsNullOrEmpty(size) && GeneratorName != "assigned")
            {
                context.LogWarning("The 'size' value of the Identifier '" + field + "' of the Entity '" + this.Entity.type + "' will be ignored because the generator name is not 'assigned'.", "013", this.Entity);
            }
        }
    }
}
